home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / ds3100.md / devSmem.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  14KB  |  435 lines

  1. /* 
  2.  * devSmem.c --
  3.  *
  4.  *    Stubs to implement /dev/smem.  Allow reading and writing
  5.  *      to kernel memory.
  6.  *
  7.  *
  8.  * Copyright 1987 Regents of the University of California
  9.  * All rights reserved.
  10.  */
  11.  
  12. #ifndef lint
  13. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/ds3100.md/devSmem.c,v 9.1 92/08/13 15:52:35 secor Exp $ SPRITE (Berkeley)";
  14. #endif not lint
  15.  
  16. #include "sprite.h"
  17. #include "fs.h"
  18. #include <vmPmaxConst.h>
  19. #include <dbg.h>
  20. #define NOGAP
  21.  
  22. static char smemBuf[1024];
  23. extern int vm_PageSize;
  24. extern int mach_KernStackSize;
  25. extern int vmBlockCacheEndAddr;
  26. extern int vmBlockCacheBaseAddr;
  27. extern int vmStackEndAddr;
  28. extern int vmStackBaseAddr;
  29. extern int vmMemEnd;
  30. extern int vmBootEnd;
  31. extern int mach_KernStart;
  32. extern int mach_CodeStart;
  33. extern Mach_DebugState mach_DebugState;
  34. static void     DebugToRegState _ARGS_((Mach_DebugState *debugPtr,
  35.                         Mach_RegState *regPtr));
  36.  
  37.  
  38. /*
  39.  *----------------------------------------------------------------------
  40.  *
  41.  *  Dev_SmemRead --
  42.  *
  43.  *    Return number of bytes read and SUCCESS if nonzero bytes returned.
  44.  *      Return SYS_ARG_NOACCESS if supplied address is unreadable, and
  45.  *      SYS_INVALID_ARG if supplied address is not valid.
  46.  *
  47.  * Results:
  48.  *    A standard Sprite return status.
  49.  *
  50.  * Side effects:
  51.  *    None.
  52.  *
  53.  *----------------------------------------------------------------------
  54.  */
  55. /*ARGSUSED*/
  56. ReturnStatus
  57. Dev_SmemRead(devicePtr, readPtr, replyPtr)
  58.     Fs_Device *devicePtr;
  59.     Fs_IOParam    *readPtr;    /* Read parameter block */
  60.     Fs_IOReply    *replyPtr;    /* Return length and signal */ 
  61. {
  62.   int status, bytesLeft;
  63.   int kernelAddress;
  64.   int numPages, bytesInPage;
  65.   char *bufPtr;
  66.   StopInfo stopInfo;
  67.   Dbg_DumpBounds currentBounds;
  68.   
  69.   stopInfo.codeStart = (int)mach_CodeStart;
  70.   stopInfo.trapType = (mach_DebugState.causeReg & MACH_CR_EXC_CODE) >>
  71.     MACH_CR_EXC_CODE_SHIFT;
  72.   DebugToRegState(&mach_DebugState, &(stopInfo.regs));
  73.   currentBounds.pageSize = vm_PageSize;
  74.   currentBounds.stackSize = mach_KernStackSize;
  75.   currentBounds.kernelCodeStart = (unsigned int) mach_KernStart;
  76.   currentBounds.kernelCodeSize  =
  77.     (unsigned int) (vmBootEnd - mach_KernStart);
  78.   currentBounds.kernelDataStart  = VMMACH_VIRT_CACHED_START;
  79.   currentBounds.kernelDataSize   = (unsigned int)
  80.     (vmMemEnd - VMMACH_VIRT_CACHED_START);
  81.   currentBounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
  82.   currentBounds.kernelStacksSize = (unsigned int)
  83.     (vmStackEndAddr - vmStackBaseAddr);
  84.   currentBounds.fileCacheStart   = (unsigned int)vmBlockCacheBaseAddr;
  85.   currentBounds.fileCacheSize    = (unsigned int) (vmBlockCacheEndAddr -
  86.                         vmBlockCacheBaseAddr);
  87.   kernelAddress = readPtr->offset;
  88.   bytesLeft = readPtr->length;
  89.   bufPtr = readPtr->buffer;
  90.  
  91.   /* Get part or all of stop info if requested. */
  92.   if (kernelAddress < sizeof(StopInfo)) {
  93.     if (bytesLeft + kernelAddress <= sizeof(StopInfo)) {
  94.       bcopy(((char *)&stopInfo) + kernelAddress, readPtr->buffer, readPtr->length);
  95.       replyPtr->length = readPtr->length;
  96.       return(SUCCESS);
  97.     }
  98.     bcopy(((char *)&stopInfo) + kernelAddress, readPtr->buffer, sizeof(StopInfo) - kernelAddress);
  99.     bytesLeft -= sizeof(StopInfo) - kernelAddress;
  100.     bufPtr += sizeof(StopInfo) - kernelAddress;
  101.     kernelAddress = sizeof(StopInfo);
  102.   }
  103.   
  104.   /* Get part or all of dump bounds if requested. */
  105.   if (kernelAddress < (sizeof(StopInfo) + sizeof(Dbg_DumpBounds))) {
  106.     if (bytesLeft + kernelAddress <= sizeof(StopInfo) + sizeof(Dbg_DumpBounds)) {
  107.       bcopy(((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, bufPtr, bytesLeft);
  108.       replyPtr->length = readPtr->length;
  109.       return(SUCCESS);
  110.     }
  111.     bcopy(((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, bufPtr, sizeof(Dbg_DumpBounds));
  112.     bytesLeft -= sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
  113.     bufPtr += sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
  114.     kernelAddress = sizeof(StopInfo) + sizeof(Dbg_DumpBounds);
  115.   }
  116.  
  117.   /* Set address to beginning of kernel memory. */
  118.   kernelAddress += mach_KernStart - (sizeof(StopInfo) + sizeof(Dbg_DumpBounds));
  119.  
  120.   /* Make sure offset is valid. */
  121. #ifdef NOGAP
  122.   if (kernelAddress > vmBootEnd) {
  123.     kernelAddress += VMMACH_VIRT_CACHED_START - vmBootEnd;
  124.   }
  125.   if (kernelAddress > vmMemEnd) {
  126.     kernelAddress += vmStackBaseAddr - vmMemEnd;
  127.   }
  128.   if (kernelAddress > vmStackEndAddr) {
  129.     kernelAddress += vmBlockCacheBaseAddr - vmStackEndAddr;
  130.   }
  131.   if (kernelAddress > vmBlockCacheEndAddr) {
  132.     return (SYS_INVALID_ARG);
  133.   }
  134. #else
  135.   if (kernelAddress > vmBootEnd &&
  136.       kernelAddress < VMMACH_VIRT_CACHED_START) {
  137.     return(SYS_INVALID_ARG);
  138.   }n
  139.   if (kernelAddress > vmMemEnd &&
  140.       kernelAddress < vmStackBaseAddr) {
  141.     return(SYS_INVALID_ARG);
  142.   }
  143.   if (kernelAddress > vmStackEndAddr &&
  144.       kernelAddress < vmBlockCacheBaseAddr) {
  145.     return(SYS_INVALID_ARG);
  146.   }
  147.   if (kernelAddress > vmBlockCacheEndAddr) {
  148.     return(SYS_INVALID_ARG);
  149.   }
  150. #endif
  151.   
  152.   /* Find number of pages that request spans. */
  153.   numPages = ((kernelAddress + bytesLeft - 1) >> VMMACH_PAGE_SHIFT) - 
  154.     (kernelAddress >> VMMACH_PAGE_SHIFT);
  155.   if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
  156.     replyPtr->length = 0;
  157.     return(SYS_ARG_NOACCESS);
  158.   }
  159.   bytesInPage = vm_PageSize - (kernelAddress & (vm_PageSize-1));
  160.   if (bytesLeft < bytesInPage) {
  161.     bcopy(kernelAddress, bufPtr, bytesLeft);
  162.     replyPtr->length = readPtr->length;
  163.     return(SUCCESS);
  164.   }
  165.   bcopy(kernelAddress, bufPtr, bytesInPage);
  166.   bytesLeft -= bytesInPage;
  167.   bufPtr += vm_PageSize;
  168.  
  169.   /* Make each page accessible, if possible and copy it into 
  170.      return buffer. */
  171.   while (numPages > 0) {
  172.     if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
  173.       replyPtr->length = 0;
  174.       return(SYS_ARG_NOACCESS);
  175.     }
  176.     if (bytesLeft < vm_PageSize) {
  177.       bcopy(kernelAddress, bufPtr, bytesLeft);
  178.       replyPtr->length = readPtr->length;
  179.       return(SUCCESS);
  180.     }
  181.     bcopy(kernelAddress, bufPtr, vm_PageSize);
  182.     bytesLeft -= vm_PageSize;
  183.     bufPtr += vm_PageSize;
  184.     numPages--;
  185.   }
  186.   replyPtr->length = readPtr->length;
  187.   return(SUCCESS);
  188. }
  189.  
  190.  
  191. /*
  192.  *----------------------------------------------------------------------
  193.  *
  194.  *  Dev_SmemWrite --
  195.  *
  196.  *    Writes if it can, and returns SUCCESS if it wrote.
  197.  *
  198.  * Results:
  199.  *    A standard Sprite return status.
  200.  *
  201.  * Side effects:
  202.  *    None.
  203.  *
  204.  *----------------------------------------------------------------------
  205.  */
  206. /*ARGSUSED*/
  207. ReturnStatus
  208. Dev_SmemWrite(devicePtr, writePtr, replyPtr)
  209.     Fs_Device *devicePtr;
  210.     Fs_IOParam    *writePtr;    /* Standard write parameter block */
  211.     Fs_IOReply    *replyPtr;    /* Return length and signal */
  212. {
  213.   int status, bytesLeft;
  214.   int kernelAddress;
  215.   int numPages, bytesInPage;
  216.   char *bufPtr;
  217.   StopInfo stopInfo;
  218.   Dbg_DumpBounds currentBounds;
  219.   
  220.   stopInfo.codeStart = (int)mach_CodeStart;
  221.   stopInfo.trapType = (mach_DebugState.causeReg & MACH_CR_EXC_CODE) >>
  222.     MACH_CR_EXC_CODE_SHIFT;
  223.   DebugToRegState(&mach_DebugState, &(stopInfo.regs));
  224.   currentBounds.pageSize = vm_PageSize;
  225.   currentBounds.stackSize = mach_KernStackSize;
  226.   currentBounds.kernelCodeStart = (unsigned int) mach_KernStart;
  227.   currentBounds.kernelCodeSize  =
  228.     (unsigned int) (vmBootEnd - mach_KernStart);
  229.   currentBounds.kernelDataStart  = VMMACH_VIRT_CACHED_START;
  230.   currentBounds.kernelDataSize   = (unsigned int)
  231.     (vmMemEnd - VMMACH_VIRT_CACHED_START);
  232.   currentBounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
  233.   currentBounds.kernelStacksSize = (unsigned int)
  234.     (vmStackEndAddr - vmStackBaseAddr);
  235.   currentBounds.fileCacheStart   = (unsigned int)vmBlockCacheBaseAddr;
  236.   currentBounds.fileCacheSize    = (unsigned int) (vmBlockCacheEndAddr -
  237.                         vmBlockCacheBaseAddr);
  238.   kernelAddress = writePtr->offset;
  239.   bytesLeft = writePtr->length;
  240.   bufPtr = writePtr->buffer;
  241.  
  242.   /* Get part or all of stop info if requested. */
  243.   if (kernelAddress < sizeof(StopInfo)) {
  244.     if (bytesLeft + kernelAddress <= sizeof(StopInfo)) {
  245.       bcopy(writePtr->buffer, ((char *)&stopInfo) + kernelAddress, writePtr->length);
  246.       replyPtr->length = writePtr->length;
  247.       return(SUCCESS);
  248.     }
  249.     bcopy(writePtr->buffer, ((char *)&stopInfo) + kernelAddress, sizeof(StopInfo) - kernelAddress);
  250.     bytesLeft -= sizeof(StopInfo) - kernelAddress;
  251.     bufPtr += sizeof(StopInfo) - kernelAddress;
  252.     kernelAddress = sizeof(StopInfo);
  253.   }
  254.   
  255.   /* Get part or all of dump bounds if requested. */
  256.   if (kernelAddress < (sizeof(StopInfo) + sizeof(Dbg_DumpBounds))) {
  257.     if (bytesLeft + kernelAddress <= sizeof(StopInfo) + sizeof(Dbg_DumpBounds)) {
  258.       bcopy(bufPtr, ((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, bytesLeft);
  259.       replyPtr->length = writePtr->length;
  260.       return(SUCCESS);
  261.     }
  262.     bcopy(bufPtr, ((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, sizeof(Dbg_DumpBounds));
  263.     bytesLeft -= sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
  264.     bufPtr += sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
  265.     kernelAddress = sizeof(StopInfo) + sizeof(Dbg_DumpBounds);
  266.   }
  267.  
  268.   /* Set address to beginning of kernel memory. */
  269.   kernelAddress += mach_KernStart - (sizeof(StopInfo) + sizeof(Dbg_DumpBounds));
  270.  
  271.   /* Make sure offset is valid. */
  272. #ifdef NOGAP
  273.   if (kernelAddress > vmBootEnd) {
  274.     kernelAddress += VMMACH_VIRT_CACHED_START - vmBootEnd;
  275.   }
  276.   if (kernelAddress > vmMemEnd) {
  277.     kernelAddress += vmStackBaseAddr - vmMemEnd;
  278.   }
  279.   if (kernelAddress > vmStackEndAddr) {
  280.     kernelAddress += vmBlockCacheBaseAddr - vmStackEndAddr;
  281.   }
  282.   if (kernelAddress > vmBlockCacheEndAddr) {
  283.     return (SYS_INVALID_ARG);
  284.   }
  285. #else
  286.   if (kernelAddress > vmBootEnd &&
  287.       kernelAddress < VMMACH_VIRT_CACHED_START) {
  288.     return(SYS_INVALID_ARG);
  289.   }n
  290.   if (kernelAddress > vmMemEnd &&
  291.       kernelAddress < vmStackBaseAddr) {
  292.     return(SYS_INVALID_ARG);
  293.   }
  294.   if (kernelAddress > vmStackEndAddr &&
  295.       kernelAddress < vmBlockCacheBaseAddr) {
  296.     return(SYS_INVALID_ARG);
  297.   }
  298.   if (kernelAddress > vmBlockCacheEndAddr) {
  299.     return(SYS_INVALID_ARG);
  300.   }
  301. #endif
  302.   
  303.   /* Find number of pages that request spans. */
  304.   numPages = ((kernelAddress + bytesLeft - 1) >> VMMACH_PAGE_SHIFT) - 
  305.     (kernelAddress >> VMMACH_PAGE_SHIFT);
  306.   if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
  307.     replyPtr->length = 0;
  308.     return(SYS_ARG_NOACCESS);
  309.   }
  310.   bytesInPage = vm_PageSize - (kernelAddress & (vm_PageSize-1));
  311.   if (bytesLeft < bytesInPage) {
  312.     bcopy(bufPtr, kernelAddress, bytesLeft);
  313.     replyPtr->length = writePtr->length;
  314.     return(SUCCESS);
  315.   }
  316.   bcopy(bufPtr, kernelAddress, bytesInPage);
  317.   bytesLeft -= bytesInPage;
  318.   bufPtr += vm_PageSize;
  319.  
  320.   /* Make each page accessible, if possible and copy it into 
  321.      return buffer. */
  322.   while (numPages > 0) {
  323.     if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
  324.       replyPtr->length = 0;
  325.       return(SYS_ARG_NOACCESS);
  326.     }
  327.     if (bytesLeft < vm_PageSize) {
  328.       bcopy(bufPtr, kernelAddress, bytesLeft);
  329.       replyPtr->length = writePtr->length;
  330.       return(SUCCESS);
  331.     }
  332.     bcopy(bufPtr, kernelAddress, vm_PageSize);
  333.     bytesLeft -= vm_PageSize;
  334.     bufPtr += vm_PageSize;
  335.     numPages--;
  336.   }
  337.   replyPtr->length = writePtr->length;
  338.   return(SUCCESS);
  339. }
  340.  
  341.  
  342. /*
  343.  *----------------------------------------------------------------------
  344.  *
  345.  * Dev_SmemIOControl --
  346.  *
  347.  *    This procedure handles IOControls for /dev/smem and other
  348.  *    devices.  It refuses all IOControls except for a few of
  349.  *    the generic ones, for which it does nothing.
  350.  *
  351.  * Results:
  352.  *    A standard Sprite return status.
  353.  *
  354.  * Side effects:
  355.  *    None.
  356.  *
  357.  *----------------------------------------------------------------------
  358.  */
  359.  
  360. /* ARGSUSED */
  361. ReturnStatus
  362. Dev_SmemIOControl(devicePtr, ioctlPtr, replyPtr)
  363.     Fs_Device            *devicePtr;
  364.     Fs_IOCParam        *ioctlPtr;
  365.     Fs_IOReply        *replyPtr;
  366. {
  367.     if ((ioctlPtr->command == IOC_GET_FLAGS)
  368.     || (ioctlPtr->command == IOC_SET_FLAGS)
  369.     || (ioctlPtr->command == IOC_SET_BITS)
  370.     || (ioctlPtr->command == IOC_CLEAR_BITS)
  371.     || (ioctlPtr->command == IOC_REPOSITION)) {
  372.     return SUCCESS;
  373.     }
  374.     return GEN_NOT_IMPLEMENTED;
  375. }
  376.  
  377. /*
  378.  *----------------------------------------------------------------------
  379.  *
  380.  * Dev_SmemSelect --
  381.  *
  382.  *    This procedure handles selects for /dev/smem and other
  383.  *    devices that are always ready.
  384.  *
  385.  * Results:
  386.  *    The device is indicated to be readable and writable.
  387.  *
  388.  * Side effects:
  389.  *    None.
  390.  *
  391.  *----------------------------------------------------------------------
  392.  */
  393.  
  394. /* ARGSUSED */
  395. ReturnStatus
  396. Dev_SmemSelect(devicePtr, readPtr, writePtr, exceptPtr)
  397.     Fs_Device    *devicePtr;    /* Ignored. */
  398.     int    *readPtr;        /* Read bit to clear if not readable */
  399.     int    *writePtr;        /* Write bit to clear if not readable */
  400.     int    *exceptPtr;        /* Except bit to clear if not readable */
  401. {
  402.     *exceptPtr = 0;
  403.     return(SUCCESS);
  404. }
  405.  
  406. /*
  407.  *----------------------------------------------------------------------
  408.  *
  409.  * DebugToRegState --
  410.  *
  411.  *      Converts a Mach_DebugState to Mach_RegState.
  412.  *
  413.  * Results:
  414.  *      None.
  415.  *
  416.  * Side effects:
  417.  *      None.
  418.  *
  419.  *----------------------------------------------------------------------
  420.  */
  421. static void
  422. DebugToRegState(debugPtr, regPtr)
  423.     Mach_DebugState     *debugPtr;
  424.     Mach_RegState       *regPtr;
  425. {
  426.     regPtr->pc = (Address) debugPtr->excPC;
  427.     bcopy((char *) debugPtr->regs, (char *) regPtr->regs,
  428.         MACH_NUM_GPRS * sizeof(int));
  429.     bcopy((char *) debugPtr->fpRegs, (char *) regPtr->fpRegs,
  430.         MACH_NUM_FPRS * sizeof(int));
  431.     regPtr->fpStatusReg = debugPtr->fpCSR;
  432.     regPtr->mfhi = debugPtr->multHi;
  433.     regPtr->mflo = debugPtr->multLo;
  434. }
  435.